package com.chaodriod.common.utils.screen;

import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;

import com.chaodriod.common.utils.Utils;

import java.lang.reflect.Method;

/**
 * Created by CHEN on 2017/12/11.
 */

public class ScreenUtils {

    private ScreenUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    public static WindowManager getWindowManager() {
        return (WindowManager) Utils.getContext().getSystemService(Context.WINDOW_SERVICE);
    }

    public static Display getDefaultDisplay() {
        return getWindowManager().getDefaultDisplay();
    }

    public static DisplayMetrics getDisplayMetrics() {
        DisplayMetrics metric = new DisplayMetrics();
        getDefaultDisplay().getMetrics(metric);
        return metric;
    }

    /**
     * 获取屏幕的宽度（单位：px）
     *
     * @return 屏幕宽
     * android4.0之后有了虚拟按键，横屏模式下，有虚拟按键的系统调用本方法尺寸会减去虚拟按键的尺寸。
     */
    public static int getScreenWidth() {
        return getDisplayMetrics().widthPixels;
    }

    /**
     * 获取屏幕的高度（单位：px）
     *
     * @return 屏幕高
     * android4.0之后有了虚拟按键，竖屏模式下，有虚拟按键的系统调用本方法尺寸会减去虚拟按键的尺寸。
     */
    public static int getScreenHeight() {
        return getDisplayMetrics().heightPixels;
    }

    /**
     * 获取屏幕真正的尺寸（Point）
     *
     * @return 屏幕真正的尺寸 Point
     */
    public static Point getScreenRealSize() {
        Point point = new Point();
        try {
            Display display = getDefaultDisplay();
            DisplayMetrics metrics = new DisplayMetrics();
            display.getMetrics(metrics);
            if (android.os.Build.VERSION.SDK_INT >= 17) {
                Point size = new Point();
                display.getRealSize(size);
            } else if (android.os.Build.VERSION.SDK_INT < 17
                    && android.os.Build.VERSION.SDK_INT >= 14) {
                Method mGetRawH = Display.class.getMethod("getRawHeight");
                Method mGetRawW = Display.class.getMethod("getRawWidth");
                point.x = (Integer) mGetRawW.invoke(display);
                point.y = (Integer) mGetRawH.invoke(display);
            } else {
                point.x = metrics.widthPixels;
                point.y = metrics.heightPixels;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return point;
    }

    /**
     * 获取屏幕真正的宽度（单位：px）
     *
     * @return 屏幕真正的宽度
     */
    public static int getScreenRealWidth() {
        int realWidth = 0, realHeight = 0;
        try {
            Display display = getDefaultDisplay();
            DisplayMetrics metrics = new DisplayMetrics();
            display.getMetrics(metrics);
            if (android.os.Build.VERSION.SDK_INT >= 17) {
                Point size = new Point();
                display.getRealSize(size);
                realWidth = size.x;
                realHeight = size.y;
            } else if (android.os.Build.VERSION.SDK_INT < 17
                    && android.os.Build.VERSION.SDK_INT >= 14) {
                Method mGetRawH = Display.class.getMethod("getRawHeight");
                Method mGetRawW = Display.class.getMethod("getRawWidth");
                realWidth = (Integer) mGetRawW.invoke(display);
                realHeight = (Integer) mGetRawH.invoke(display);
            } else {
                realWidth = metrics.widthPixels;
                realHeight = metrics.heightPixels;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return realWidth;
    }

    /**
     * 获取屏幕真正的高度（单位：px）
     *
     * @return 屏幕真正的高度
     */
    public static int getScreenRealHeight() {
        int realWidth = 0, realHeight = 0;
        try {
            Display display = getDefaultDisplay();
            DisplayMetrics metrics = new DisplayMetrics();
            display.getMetrics(metrics);
            if (android.os.Build.VERSION.SDK_INT >= 17) {
                Point size = new Point();
                display.getRealSize(size);
                realWidth = size.x;
                realHeight = size.y;
            } else if (android.os.Build.VERSION.SDK_INT < 17
                    && android.os.Build.VERSION.SDK_INT >= 14) {
                Method mGetRawH = Display.class.getMethod("getRawHeight");
                Method mGetRawW = Display.class.getMethod("getRawWidth");
                realWidth = (Integer) mGetRawW.invoke(display);
                realHeight = (Integer) mGetRawH.invoke(display);
            } else {
                realWidth = metrics.widthPixels;
                realHeight = metrics.heightPixels;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return realHeight;
    }

    /**
     * 获取状态栏StatusBar高度(px)
     *
     * @return 状态栏高度(px)
     */
    public static int getStatusBarHeight() {
        Resources resources = Utils.getContext().getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelSize(resourceId);
    }

    /**
     * 获取ActionBar高度
     *
     * @param activity activity
     * @return ActionBar高度
     */
    public static int getActionBarHeight(@NonNull final Activity activity) {
        TypedValue tv = new TypedValue();
        if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
            return TypedValue.complexToDimensionPixelSize(tv.data, activity.getResources().getDisplayMetrics());
        }
        return 0;
    }

    /**
     * 获取导航栏（虚拟按键）NavigationBar高度(px)
     *
     * @return 导航栏高度(px), 0代表不存在
     */
    public static int getNavigationBarHeight() {
        Resources res = Utils.getContext().getResources();
        int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
        return res.getDimensionPixelSize(resourceId);
    }

    /**
     * 获取屏幕的像素密度（Dpi）
     */
    public static int getDensityDpi() {
        return getDisplayMetrics().densityDpi;
    }

    /**
     * dp转换px
     */
    public static int dp2px(float dpValue) {
        float scale = getDensityDpi();
        return (int) (dpValue * (scale / 160) + 0.5f);
    }

    public static int dp2px(Context context, float dpValue) {
        float scale = getDensityDpi();
        return (int) (dpValue * (scale / 160) + 0.5f);
    }

    /**
     * px转换dp
     */
    public static int px2dp(float pxValue) {
        int scale = getDensityDpi();
        return (int) (pxValue / scale);
    }

    public static int px2dp(Context context, float pxValue) {
        int scale = getDensityDpi();
        return (int) (pxValue / scale);
    }

    /**
     * Value of sp to value of px.
     *
     * @param spValue The value of sp.
     * @return value of px
     */
    public static int sp2px(final float spValue) {
        final float fontScale = Utils.getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    /**
     * Value of px to value of sp.
     *
     * @param pxValue The value of px.
     * @return value of sp
     */
    public static int px2sp(final float pxValue) {
        final float fontScale = Utils.getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    /**
     * 设置系统UI
     * View.SYSTEM_UI_FLAG_VISIBLE：显示状态栏，Activity不全屏显示(恢复到有状态的正常情况)。
     * View.INVISIBLE：隐藏状态栏，同时Activity会伸展全屏显示。
     * View.SYSTEM_UI_FLAG_FULLSCREEN：Activity全屏显示，且状态栏被隐藏覆盖掉。
     * View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN：Activity全屏显示，但状态栏不会被隐藏覆盖，状态栏依然可见，Activity顶端布局部分会被状态遮住。
     * View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION：效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
     * View.SYSTEM_UI_LAYOUT_FLAGS = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
     * View.SYSTEM_UI_FLAG_HIDE_NAVIGATION：隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。
     * View.SYSTEM_UI_FLAG_LOW_PROFILE：状态栏显示处于低能显示状态(low profile模式)，状态栏上一些图标显示会被隐藏。
     * <p>
     * View.SYSTEM_UI_FLAG_LAYOUT_STABLE:防止系统栏隐藏时 Activity的大小发生变化
     * View.SYSTEM_UI_FLAG_IMMERSIVE：沉浸模式，触摸屏幕上下边沿退出沉浸模式
     * View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY：粘性沉浸模式，触摸屏幕上下边沿临时退出沉浸模式，一段时间后自动恢复沉浸模式
     * immersive类的标签只有在与SYSTEM_UI_FLAG_HIDE_NAVIGATION,SYSTEM_UI_FLAG_FULLSCREEN中一个或两个一起使用的时候才会生效。
     * View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR：把状态栏标记为浅色，然后状态栏的字体颜色自动转换为深色。
     * View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
     *
     * @param activity activity
     */

    public final static int FLAG_SHOW_STATUS = View.SYSTEM_UI_FLAG_VISIBLE;
//    public final static int FLAG_HIDE_STATUS = View.INVISIBLE;//隐藏状态栏
    public final static int FLAG_HIDE_STATUS = View.SYSTEM_UI_FLAG_FULLSCREEN;//效果同上，状态栏被Activity覆盖
    public final static int FLAG_INVADE_STATUS = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;//侵入状态栏，Activity顶端布局部分会被状态遮住
    //    public final static int FLAG_INVADE_STATUS = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;//效果同上
//    public final static int FLAG_INVADE_STATUS = View.SYSTEM_UI_LAYOUT_FLAGS;//效果同上
    public final static int FLAG_HIDE_NAVIGATION = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
//    public final static int FLAG_HIDE_NAVIGATION = View.SYSTEM_UI_FLAG_LOW_PROFILE;//隐藏虚拟按键或者虚拟按键的背灯

    public static void setSystemUi(@NonNull final Activity activity, int flag) {
        View decorView = activity.getWindow().getDecorView();
        decorView.setSystemUiVisibility(flag);
    }

    public static void setSystemUi(@NonNull final Activity activity, boolean showStatus, boolean showNavigation, boolean isSticky) {
        View decorView = activity.getWindow().getDecorView();
        int options = decorView.getSystemUiVisibility();
        if (!showStatus) {
            options = options | FLAG_HIDE_STATUS;
        } else {
            options = options & ~FLAG_HIDE_STATUS;
        }
        if (!showNavigation) {
            options = options | FLAG_HIDE_NAVIGATION;
        } else {
            options = options & ~FLAG_HIDE_NAVIGATION;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (isSticky) {
                options = options | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            } else {
                options = options & ~View.SYSTEM_UI_FLAG_IMMERSIVE;
            }
        }
        decorView.setSystemUiVisibility(options);
    }

    /**
     * 隐藏状态栏
     *
     * @param activity activity
     */
    public static void hideStatusBar(@NonNull final Activity activity, boolean isSticky) {
        View decorView = activity.getWindow().getDecorView();
        int options = decorView.getSystemUiVisibility();
            options = options | FLAG_HIDE_STATUS;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (isSticky) {
                options = options | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            } else {
                options = options & ~View.SYSTEM_UI_FLAG_IMMERSIVE;
            }
        }
        decorView.setSystemUiVisibility(options);
    }

    /**
     * 显示导状态栏
     *
     * @param activity activity
     */
    public static void showStatusBar(@NonNull final Activity activity) {
        View decorView = activity.getWindow().getDecorView();
        int options = decorView.getSystemUiVisibility();
        options = options & ~FLAG_HIDE_STATUS;
        decorView.setSystemUiVisibility(options);
    }

    /**
     * 隐藏导航栏（虚拟按键）
     *
     * @param activity activity
     */
    public static void hideNavigationBar(@NonNull final Activity activity, boolean isSticky) {
        View decorView = activity.getWindow().getDecorView();
        int options = decorView.getSystemUiVisibility();
        options = options | FLAG_HIDE_NAVIGATION;
        options = options & ~FLAG_HIDE_NAVIGATION;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (isSticky) {
                options = options | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            } else {
                options = options & ~View.SYSTEM_UI_FLAG_IMMERSIVE;
            }
        }
        decorView.setSystemUiVisibility(options);
    }

    /**
     * 显示导航栏（虚拟按键）
     *
     * @param activity activity
     */
    public static void showNavigationBar(@NonNull final Activity activity) {
        View decorView = activity.getWindow().getDecorView();
        int options = decorView.getSystemUiVisibility();
        decorView.setSystemUiVisibility(options);
    }

    /**
     * 显示导航栏（虚拟按键）
     *
     * @param activity activity
     */
    public static void showSystemUI(@NonNull final Activity activity) {
        activity.getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }

    /**
     * 设置屏幕为横屏
     * <p>还有一种就是在Activity中加属性android:screenOrientation="landscape"</p>
     * <p>不设置Activity的android:configChanges时，切屏会重新调用各个生命周期，切横屏时会执行一次，切竖屏时会执行两次</p>
     * <p>设置Activity的android:configChanges="orientation"时，切屏还是会重新调用各个生命周期，切横、竖屏时只会执行一次</p>
     * <p>设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"（4.0以上必须带最后一个参数）时
     * 切屏不会重新调用各个生命周期，只会执行onConfigurationChanged方法</p>
     *
     * @param activity activity
     */
    public static void setLandscape(@NonNull final Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    /**
     * 设置屏幕为竖屏
     *
     * @param activity activity
     */
    public static void setPortrait(@NonNull final Activity activity) {
        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    /**
     * 判断是否横屏
     *
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isLandscape() {
        return Utils.getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
    }

    /**
     * 判断是否竖屏
     *
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isPortrait() {
        return Utils.getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
    }

    /**
     * 获取屏幕旋转角度
     *
     * @param activity activity
     * @return 屏幕旋转角度
     */
    public static int getScreenRotation(@NonNull final Activity activity) {
        switch (activity.getWindowManager().getDefaultDisplay().getRotation()) {
            default:
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
    }

    /**
     * 判断是否锁屏
     *
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isScreenLock() {
        KeyguardManager km = (KeyguardManager) Utils.getContext().getSystemService(Context.KEYGUARD_SERVICE);
        return km.inKeyguardRestrictedInputMode();
    }

    /**
     * 设置进入休眠时长
     * <p>需添加权限 {@code <uses-permission android:name="android.permission.WRITE_SETTINGS" />}</p>
     *
     * @param duration 时长
     */
    public static void setSleepDuration(final int duration) {
        Settings.System.putInt(Utils.getContext().getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, duration);
    }

    /**
     * 获取进入休眠时长
     *
     * @return 进入休眠时长，报错返回-123
     */
    public static int getSleepDuration() {
        try {
            return Settings.System.getInt(Utils.getContext().getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            return -123;
        }
    }

    /**
     * 判断是否是平板
     *
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isTablet() {
        return (Utils.getContext().getResources().getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE;
    }

    /**
     * 截屏
     *
     * @param activity activity
     * @return Bitmap
     */
    public static Bitmap screenShot(@NonNull final Activity activity) {
        return screenShot(activity, true);
    }

    /**
     * 截屏
     *
     * @param activity activity
     * @return Bitmap
     */
    public static Bitmap screenShot(@NonNull final Activity activity, boolean isDeleteStatusBar) {
        View decorView = activity.getWindow().getDecorView();
        decorView.setDrawingCacheEnabled(true);
        decorView.buildDrawingCache();
        Bitmap bmp = decorView.getDrawingCache();
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        Bitmap ret;
        if (isDeleteStatusBar) {
            Resources resources = activity.getResources();
            int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
            int statusBarHeight = resources.getDimensionPixelSize(resourceId);
            ret = Bitmap.createBitmap(bmp, 0, statusBarHeight, dm.widthPixels, dm.heightPixels - statusBarHeight);
        } else {
            ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);
        }
        decorView.destroyDrawingCache();
        return ret;
    }
}
